namespace AwesomiumDotNet
{
	/// <summary>
	/// JSValue is a class that represents a Javascript value.
	/// It can be initialized from and converted to several types:
	/// boolean, integer, double, string
	/// </summary>
	public ref class JSValue
	{
	private:
		enum class VariantType {
			VariantType_Null,
			VariantType_Boolean,
			VariantType_Integer,
			VariantType_Double,
			VariantType_String
		};

	private: VariantType type;
	private: String^ stringValue;
	private: bool booleanValue;
	private: int integerValue;
	private: double doubleValue;

	public:
	  /// <summary>Creates a null JSValue.</summary>
		JSValue()
		{
			type = VariantType::VariantType_Null;
		}

	public:
	  /// <summary>Creates a JSValue initialized with a boolean.</summary>
		JSValue(bool value)
		{
			type = VariantType::VariantType_Boolean;
			booleanValue = value;
		}

	public:
	  /// <summary>Creates a JSValue initialized with an integer.</summary>
		JSValue(int value)
		{
			type = VariantType::VariantType_Integer;
			integerValue = value;
		}

	public:
	  /// <summary>Creates a JSValue initialized with a double.</summary>
		JSValue(double value)
		{
			type = VariantType::VariantType_Double;
			doubleValue = value;
		}

	public:
	  /// <summary>Creates a JSValue initialized with a string.</summary>
		JSValue(String^ value)
		{
			type = VariantType::VariantType_String;
			stringValue = value;
		}

	public:
	  /// <summary>Returns whether or not this JSValue is a boolean.</summary>
		bool IsBoolean() {
			return type == VariantType::VariantType_Boolean;
		}
	
	public:
	  /// <summary>Returns whether or not this JSValue is an integer.</summary>
		bool IsInteger() {
			return type == VariantType::VariantType_Integer;
		}

	public:
	  /// <summary>Returns whether or not this JSValue is a double.</summary>
		bool IsDouble() {
			return type == VariantType::VariantType_Double;
		}

	public:
	  /// <summary>Returns whether or not this JSValue is a string.</summary>
		bool IsString() {
			return type == VariantType::VariantType_String;
		}
	
	public:
	  /// <summary>Returns whether or not this JSValue is null.</summary>
		bool IsNull() {
			return type == VariantType::VariantType_Null;
		}

	public:
	  /// <summary>Returns this JSValue as a string (converting if necessary).</summary>
		virtual String^ ToString() override {
			if (type == VariantType::VariantType_String)
				return stringValue;
			
			else if (type == VariantType::VariantType_Boolean)
				return booleanValue.ToString()->ToLower();
			
			else if (type == VariantType::VariantType_Integer)
				return integerValue.ToString();
			
			else if (type == VariantType::VariantType_Double)
				return doubleValue.ToString();

			return "";
		}

	public:
	  /// <summary>Returns this JSValue as a boolean.</summary>
		bool ToBoolean() {
			return booleanValue;
		}

	public:
	  /// <summary>Returns this JSValue as n integer.</summary>
		int ToInteger() {
			return integerValue;
		}

	public:
	  /// <summary>Returns this JSValue as n double.</summary>
		double ToDouble() {
			return doubleValue;
		}

	};
}
